package com.hm.ibsm.auto;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.task.TaskExecutor;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import com.hm.ibsm.auto.handler.GrpcClientInterceptor;
import com.hm.ibsm.auto.handler.GrpcServerInterceptor;
import com.hm.ibsm.util.RedisObjectSerializer;
import com.hm.ibsm.util.RedisUtilFactory;
import com.hm.ibsm.util.RedisUtilLock;
import com.querydsl.jpa.impl.JPAQueryFactory;

import net.devh.springboot.autoconfigure.grpc.client.GlobalClientInterceptorConfigurerAdapter;
import net.devh.springboot.autoconfigure.grpc.client.GlobalClientInterceptorRegistry;
import net.devh.springboot.autoconfigure.grpc.server.GlobalServerInterceptorConfigurerAdapter;
import net.devh.springboot.autoconfigure.grpc.server.GlobalServerInterceptorRegistry;

/**
 * @author shishun.wang
 * @date 下午3:50:30 2017年2月2日
 * @version 1.0
 * @param <T>
 * @describe
 */
@EnableAsync // 配置 @Async 异步生效
@Configuration
@EnableConfigurationProperties({ ManageProperties.class })
public class ManageAutoConfiguration<T> {

	@PersistenceContext
	EntityManager entityManager;

	@Autowired
	private ManageProperties manageProperties;

	@Autowired
	private BeanFactory beanFactory;

	@Autowired
	private RedisTemplate<String, Object> redisTemplate;

	@Bean
	public JPAQueryFactory jpaQueryFactory() {
		return new JPAQueryFactory(entityManager);
	}

	@Bean
	public ManageProperties manageProperties() {
		return manageProperties;
	}

	@Bean
	public TaskExecutor taskExecutor() {
		ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
		executor.setCorePoolSize(5);
		executor.setKeepAliveSeconds(300);
		executor.setMaxPoolSize(10);
		executor.setQueueCapacity(25);
		return executor;
	}

	@Bean
	public GlobalServerInterceptorConfigurerAdapter globalServerInterceptorConfigurerAdapter() {
		return new GlobalServerInterceptorConfigurerAdapter() {
			@Override
			public void addServerInterceptors(GlobalServerInterceptorRegistry registry) {
				registry.addServerInterceptors(new GrpcServerInterceptor());
			}
		};
	}

	@Bean
	public GlobalClientInterceptorConfigurerAdapter globalClientInterceptorConfigurerAdapter() {
		return new GlobalClientInterceptorConfigurerAdapter() {

			@Override
			public void addClientInterceptors(GlobalClientInterceptorRegistry registry) {
				registry.addClientInterceptors(new GrpcClientInterceptor());
			}
		};
	}

	@Bean
	public JedisConnectionFactory jedisConnectionFactory() {
		return new JedisConnectionFactory();
	}

	@Bean
	public RedisUtilFactory redisUtilFactory() {
		return new RedisUtilFactory(redisTemplate, manageProperties());
	}

	@Bean
	public RedisUtilLock redisUtilLock() {
		return new RedisUtilLock(redisTemplate, manageProperties());
	}

	@Bean
	public RedisTemplate<String, T> redisEntityTemplate() {
		RedisTemplate<String, T> redisTemplate = new RedisTemplate<String, T>();
		redisTemplate.setConnectionFactory(jedisConnectionFactory());
		redisTemplate.setKeySerializer(new StringRedisSerializer());
		redisTemplate.setValueSerializer(new RedisObjectSerializer<T>());
		return redisTemplate;
	}


	/*@Bean(name = AuthService.HTTP_INVOKER_EXPORT_CONTEXT)
	public HttpInvokerServiceExporter authService() {
		HttpInvokerServiceExporter httpInvokerServiceExporter = new HttpInvokerServiceExporter();
		httpInvokerServiceExporter.setServiceInterface(AuthService.class);
		httpInvokerServiceExporter.setService(beanFactory.getBean(AuthService.class));
		httpInvokerServiceExporter.afterPropertiesSet();
		return httpInvokerServiceExporter;
	}

	@Bean(name = DictService.HTTP_INVOKER_EXPORT_CONTEXT)
	public HttpInvokerServiceExporter dictService() {
		HttpInvokerServiceExporter httpInvokerServiceExporter = new HttpInvokerServiceExporter();
		httpInvokerServiceExporter.setServiceInterface(DictService.class);
		httpInvokerServiceExporter.setService(beanFactory.getBean(DictService.class));
		httpInvokerServiceExporter.afterPropertiesSet();
		return httpInvokerServiceExporter;
	}

	@Bean(name = MenuService.HTTP_INVOKER_EXPORT_CONTEXT)
	public HttpInvokerServiceExporter menuService() {
		HttpInvokerServiceExporter httpInvokerServiceExporter = new HttpInvokerServiceExporter();
		httpInvokerServiceExporter.setServiceInterface(MenuService.class);
		httpInvokerServiceExporter.setService(beanFactory.getBean(MenuService.class));
		httpInvokerServiceExporter.afterPropertiesSet();
		return httpInvokerServiceExporter;
	}

	@Bean(name = RoleService.HTTP_INVOKER_EXPORT_CONTEXT)
	public HttpInvokerServiceExporter roleService() {
		HttpInvokerServiceExporter httpInvokerServiceExporter = new HttpInvokerServiceExporter();
		httpInvokerServiceExporter.setServiceInterface(RoleService.class);
		httpInvokerServiceExporter.setService(beanFactory.getBean(MenuService.class));
		httpInvokerServiceExporter.afterPropertiesSet();
		return httpInvokerServiceExporter;
	}

	@Bean(name = UserService.HTTP_INVOKER_EXPORT_CONTEXT)
	public HttpInvokerServiceExporter userService() {
		HttpInvokerServiceExporter httpInvokerServiceExporter = new HttpInvokerServiceExporter();
		httpInvokerServiceExporter.setServiceInterface(UserService.class);
		httpInvokerServiceExporter.setService(beanFactory.getBean(UserService.class));
		httpInvokerServiceExporter.afterPropertiesSet();
		return httpInvokerServiceExporter;
	}*/
}
